package com.qf.hospital.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.hospital.DTO.AddUserDTO;
import com.qf.hospital.VO.SideVO;
import com.qf.hospital.VO.SysUserRoleVO;
import com.qf.hospital.constants.HospitalConstants;
import com.qf.hospital.entity.SysMenu;
import com.qf.hospital.entity.SysRole;
import com.qf.hospital.entity.SysUser;
import com.qf.hospital.entity.SysUserExample;
import com.qf.hospital.enums.HospitalExceptionEnum;
import com.qf.hospital.exception.HosptialException;
import com.qf.hospital.mapper.SysUserMapper;
import com.qf.hospital.realm.CustomRealm;
import com.qf.hospital.service.SysRoleService;
import com.qf.hospital.service.SysUserService;
import com.qf.hospital.util.ExampleUtil;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author 何星宇
 * @version V1.0
 * @Date 2021/10/15 15:37
 */

@Service
public class SysUserServiceImpl implements SysUserService {
    private Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
    @Autowired
    private SysUserMapper mapper;

    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 根据用户名查询用户信息
     * @param loginName
     * @return
     */
    @Override
    public SysUser findSysUserByLoginName(String loginName) {
        SysUserExample example = new SysUserExample();
        example.createCriteria().andLoginNameEqualTo(loginName);
        List<SysUser> sysUsers = mapper.selectByExample(example);
        if (sysUsers.size()==1){
            return sysUsers.get(0);
        }
        if (sysUsers.size()>1){
            log.info("【查询用户】 系统异常，用户存在多个");
            throw new HosptialException(HospitalExceptionEnum.SYSTEM_EXCEPTION,"用户存在多个");
        }
        return null;
    }

    /**
     * 根据用户id查询菜单信息
     * @param userId
     * @return
     */
    @Override
    public List<SideVO> findSideByUserId(Integer userId) {
        //查询数据
        List<SysMenu> sysMenuList = mapper.selectMenuByUserId(userId);
        //校验
        if (sysMenuList==null||sysMenuList.size()==0){
            return null;
        }
        //封装数据

        //创建一级菜单的map集合
        Map<Integer,SideVO> oneLevelMenuMap = new HashMap<>();
        //遍历结果
        Iterator<SysMenu> iterator = sysMenuList.iterator();
        while (iterator.hasNext()){
            //如果是一级菜单，放进oneLevelMenu集合中
            SysMenu sysMenu = iterator.next();
            if (sysMenu.getParentId()==1){
                SideVO sideVO = new SideVO();
                BeanUtils.copyProperties(sysMenu, sideVO);
                oneLevelMenuMap.put(sysMenu.getId(), sideVO);
                //将一级菜单的信息从sysMenuList删除
                iterator.remove();
            }
        }

        //将非一级菜单放进一级菜单的children属性中
        for (SysMenu sysMenu : sysMenuList) {
            //获取当前子菜单的父菜单id
            Integer parentId = sysMenu.getParentId();
            //通过id找到父菜单
            SideVO oneLevelMenu = oneLevelMenuMap.get(parentId);

            //找到了父菜单
            if (oneLevelMenu!=null){
                SideVO sideVO = new SideVO();
                BeanUtils.copyProperties(sysMenu, sideVO);
                //将子菜单封装进父菜单的children属性中
                oneLevelMenu.getChildren().add(sideVO);
            }
        }

        //将map集合中的数据封装到list返回结果中
        List<SideVO> result = new ArrayList<>();
        for (Map.Entry<Integer, SideVO> integerSideVOEntry : oneLevelMenuMap.entrySet()) {
            result.add(integerSideVOEntry.getValue());
        }
        return result;
    }

    /**
     * 查找所有用户
     * @param realname
     * @param loginname
     * @param address
     * @param phone
     * @param identity
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<SysUser> findAllUser(String realname, String loginname, String address, String phone, String identity, Integer page, Integer limit) {
        //执行分页
        PageHelper.startPage(page, limit);

        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        if (!StringUtils.isEmpty(realname)){
            criteria.andRealNameLike(ExampleUtil.any(realname));
        }
        if (!StringUtils.isEmpty(loginname)){
            criteria.andLoginNameLike(ExampleUtil.any(loginname));
        }
        if (!StringUtils.isEmpty(address)){
            criteria.andAddressLike(ExampleUtil.any(address));
        }
        if (!StringUtils.isEmpty(phone)){
            criteria.andPhoneLike(ExampleUtil.any(phone));
        }
        if (!StringUtils.isEmpty(identity)){
            criteria.andIdentityLike(ExampleUtil.any(identity));
        }

        List<SysUser> userList = mapper.selectByExample(example);
        PageInfo<SysUser> pageInfo = new PageInfo<>(userList);
        return pageInfo;
    }

    /**
     * 添加用户
     * @param userDTO
     */
    @Override
    @Transactional
    public void addUser(AddUserDTO userDTO) {
        //生成盐
        String salt = UUID.randomUUID().toString();
        //生成密码
        String pwd = new Md5Hash(HospitalConstants.INIT_PASSWORD,salt, CustomRealm.HASH_ITERATIONS).toString();
        //用户类型（默认为系统用户）
        Integer type = HospitalConstants.USER_TYPE_SYSTEM;

        //封装进userDTO
        userDTO.setSalt(salt);
        userDTO.setPwd(pwd);
        userDTO.setType(type);

        //
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userDTO, sysUser);
        int count = mapper.insertSelective(sysUser);
        if (count!=1){
            log.info("添加用户失败，sysUser = {}",sysUser);
            throw new HosptialException(HospitalExceptionEnum.ADDUSER_EXCEPTION);
        }
    }

    /**
     * 获取全部角色信息
     * @return
     */
    @Override
    public List<SysUserRoleVO> findUserRoleByUserId(Integer userId) {
        //查询所有角色
        List<SysRole> sysRoleList = sysRoleService.findAll();

        //根据用户id获取角色id
        List<Integer> roleId = mapper.findRoleByUserId(userId);

        //封装数据
        List<SysUserRoleVO> data = new ArrayList<>();
        for (SysRole sysRole : sysRoleList) {
            SysUserRoleVO sysUserRoleVO = new SysUserRoleVO();
            BeanUtils.copyProperties(sysRole, sysUserRoleVO);
            //判断用户的角色id是否包含当前的角色id
            if (roleId.contains(sysRole.getRoleId())){
                sysUserRoleVO.setLayChecked(true);
            }
            data.add(sysUserRoleVO);
        }

        return data;
    }

    /**
     * 保存用户角色信息
     * @param userId
     * @param ids
     */
    @Override
    @Transactional
    public void saveUserRole(Integer userId, Integer[] ids) {
        //删除用户角色信息
        mapper.deleteUserRoleByUserId(userId);

        //添加用户角色信息
        int count = mapper.addUserRoles(userId,ids);
        if (count!=ids.length){
            log.error("【系统异常】 添加用户角色信息失败，userId = {} , ids = {}",userId,ids);
            throw new HosptialException(HospitalExceptionEnum.SYSTEM_EXCEPTION,"添加用户角色信息失败");
        }
    }
}
